/* api */
import{ deleteTask, getCardDetailList, getTaskConfig, getTaskTemplateFields, getSatisfactionFields, getTaskTypesMap, getTurnOnTaskExceptionNodeInfo, search, withPart } from '@src/api/TaskApi'
/* computed */
import BizListViewTaskComputed from '@src/component/business/BizListView/Impl/BizListViewTask/BizListViewTaskComputed'
/* component */
import BizListViewTask from '@src/component/business/BizListView/Impl/BizListViewTask/BizListViewTask.tsx'
/* constants */
import { AllotTypeConvertMap, FlagConvertMap, TaskApproveConvertMap, TaskOnceConvertMap } from '@src/modules/task/model/TaskConvertMap'
import { EndDateHMS, StartDateHMS } from '@src/model/const/Date'
/* enum */
import AuthEnum from '@model/enum/AuthEnum'
import { FieldTypeMappingEnum, LogisticsFieldNameMappingEnum, TaskFieldDisplayNameMappingEnum, TaskFieldExportNameMappingEnum, TaskFieldNameMappingEnum } from '@model/enum/FieldMappingEnum'
import TableNameEnum from '@model/enum/TableNameEnum'
import ConstDataEnum from '@model/enum/ConstDataEnum'
import TaskViewPointIdEnum from '@model/enum/TaskViewPointIdEnum'
import TaskStateEnum from '@model/enum/TaskStateEnum'

/* entity */
import Field from '@model/entity/Field'
import TaskType from '@model/entity/TaskType'
import CardInfo from '@model/entity/CardInfo'
import LoginUser from '@model/entity/LoginUser/LoginUser'
import EsSort from '@model/types/EsSort'
import TaskException, { TaskExceptionReason } from '@model/entity/TaskException'
import Column from '@model/types/Column'
import TaskTypeSimple from '@model/entity/TaskTypeSimple'
/* interface */
import { TaskExportGroupChecked, TaskExportGroup } from '@src/component/business/BizListView/Impl/BizListViewTask/BizListViewTaskInterface'
/* model */
import EsTaskSearchInput from '@model/types/EsTaskSearchInput'
import { getTaskConfigResult, getTaskFilterWithPartResult, getTaskTypesResult, getTurnOnTaskExceptionNodeInfoResult, getTaskSearchListResult } from '@model/param/out/Task'
import { BatchDeleteTaskErrorMessage, BATCH_DELETE_TASK_MASSAGE, DELETE_SUCCESS_MESSAGE, PLEASE_SELECT_DATA_MESSAGE } from '@src/model/const/Alert'
import { TaskExportModel, TaskSearchListModel } from '@model/param/in/Task'
import { 
  TaskAddressFields, 
  TaskAdvancedAddressFields, 
  TaskExportGroupTextEnum, 
  TaskExportGroupValueEnum, 
  TaskLinkmanFields, 
  TaskProductFields, 
  TaskReceiptExportFields, 
  TaskTypeField, 
  UserNameConvertMap
} from '@src/component/business/BizListView/Impl/BizListViewTask/BizListViewTaskModel'
import { allExport, Inquire } from '@src/modules/task/list/TaskFieldModel'
import Page from '@model/Page'
/* service */
import { 
  getFieldName, 
  isAttachmentFiled,
  isPlanTimeField,
  isSearchField, 
  isSystemFiled, 
  isTaskNoField, 
  mergeFieldsWithProperty, 
  sortFields,
  getFieldWithFieldName,
  isCurrencyField
} from '@service/FieldService'
/* util */
import * as _ from 'lodash'
import { safeNewDate } from '@src/util/time';
import Platform from '@src/util/platform'
import { hasOwn, stringify } from '@src/util/lang/object'
import { strConcat as concat } from 'pub-bbx-utils'
import Log from '@src/util/log'
import { isArray, isEmpty, isString, isUndefined } from '@src/util/type'
import { fieldArrayToObject } from '@src/util/array'
import i18n, { t } from '@src/locales'
import { smoothLogisticsField } from '@service/LogisticsService'

interface City {
  cusCountry?: string
  cusProvince?: string
  cusCity?: string
  cusDist?: string
}

function getUserIdsForSearch(user: any, params: Record<string, any>, userKey: string): any {
  let users: any[] = params[userKey]
  let isUserArray = isArray(users) 
  
  if (user && isUserArray) return users
  
  return (
    user
      ? isUserArray
        ? users.push(user) 
        : []
      : isUserArray
        ? users
        : []
  )
}

/* 工单 曾.. 字段 的数据转换 */
function taskOnceFieldValueConvert(data: any): number | null {
  if (hasOwn(TaskOnceConvertMap, data)) {
    return TaskOnceConvertMap[data]
  }
  
  return data
}

/* 工单 审批状态 的数据转换 */
function taskApproveValueConvert(data: any): number | null {
  if (hasOwn(TaskApproveConvertMap, data)) {
    return TaskApproveConvertMap[data]
  }
  
  return data
}

class BizListViewTaskMethods<T, P> extends BizListViewTaskComputed<T, P> {
  
  /**
   * @description 高级搜索
   */
  public advancedSearch() {
    // @ts-ignore
    const { params, repeatBool } = this.TaskSearchPanelComponent?.buildParams()
    
    Log.info(params, 'params', this.advancedSearch.name)
    
    // 存在重复项
    if (repeatBool) {
      this.page = new Page()
      return 
    } 
    // 初始化工单类型所有工单字段列表
    this.initializeTaskTypeAllFields()
    // 工单类型数据处理
    // this.advancedSearchSetCurrentTaskType(params)
    
    this.clearPageList()
    this.searchParams.pageNum = 1
    this.params.moreConditions = params
    
    this.onPaginationPageNumChangedHandler(this.searchParams.pageNum);
  }
  
  // public advancedSearchSetCurrentTaskType(params: Record<string, any>): void {
  //   const currentTaskTypeId: string | undefined = params?.taskType
    
  //   // 不存在工单类型id
  //   if (!currentTaskTypeId) {
  //     this.currentTaskType = { id: '', templateId: '', name: '' }
  //     this.initializeTaskTypeAllFields()
  //     return
  //   }
    
  //   const taskType: TaskType | undefined = this.taskTypes.find(taskType => taskType.id === currentTaskTypeId)
    
  //   // 更新当前工单类型新
  //   this.currentTaskType = {
  //     id: currentTaskTypeId,
  //     templateId: currentTaskTypeId,
  //     name: taskType?.name || ''
  //   }
  //   // 初始化工单类型所有工单字段列表
  //   this.initializeTaskTypeAllFields()
  // }
  
  public advancedSearchColumnsFilterHandler(fields: Field[]): Field[] {
    const excludeField = new Set(['attachment', 'autograph', 'systemAutograph', 'taskNo', 'taskType', 'quality']);
    return (
      fields.filter(field => {
        const {formType, fieldName, displayName} = field;
        /** 
         * 高级搜索字段列表需要过滤掉
         * 1. 附件字段
         * 2. 非系统且不支持高级搜索的字段
         * 3. 工单编号字段
        */
        return (
          ![formType, fieldName, displayName].some(item => item && excludeField.has(item)) &&
          !isAttachmentFiled(field)
          && (isSystemFiled(field) ? true : isSearchField(field))
          && !isTaskNoField(field)
        )
      })
    )
  }
  
  /**
   * @description: 构建高级搜索面板参数
   * @return {Record<string, any>}
   */  
  public buildAdvancedSearchParams(): Record<string, any> {
    // 获取高级搜索参数
    const advancedSearchParams = this.BaseSearchPanelComponent?.buildParams() || {}
    
    // 存在工单类型数据
    if (advancedSearchParams.templateId) {
      const typeId: string = advancedSearchParams.templateId
      const taskType: TaskType | undefined = this.taskTypes.find(item => item.templateId === typeId)
      
      // 更新当前工单类型新
      this.currentTaskType = {
        id: typeId,
        templateId: typeId,
        name: taskType?.name || ''
      }
      // 初始化工单类型所有工单字段列表
      this.initializeTaskTypeAllFields()
      
    } 
    
    return advancedSearchParams
  }
  
  /**
   * @description: 构建导出列
   * @return {void}
   */  
  public buildExportColumns(): void {
    this.exportTaskColumns = [
      // 工单字段字段
      {
        label: TaskExportGroupTextEnum.Task,
        value: TaskExportGroupValueEnum.Task,
        columns: this.buildExportColumnsOfTaskFields(),
      },
      // 回执字段
      {
        label: TaskExportGroupTextEnum.TaskReceipt,
        value: TaskExportGroupValueEnum.TaskReceipt,
        columns: this.buildExportColumnsOfTaskReceiptFields(),
      },
      // 系统字段
      {
        label: TaskExportGroupTextEnum.System,
        value: TaskExportGroupValueEnum.System,
        columns: allExport.map((item: any) => {
          item.export = true
          item.label = item.displayName
          return item
        })
      },
      // 附加卡片字段
      ...this.buildExportColumnsOfTaskCardFields()
    ]
  }
  
  /**
   * @description: 构建给导出列使用的工单字段列表
   * -- 抄的工单列表
   * @return {Field[]} 给导出列使用的工单字段列表
   */
  public buildExportColumnsOfTaskFields(): Field[] {
    // 当前工单类型的工单字段列表
    const CurrentTaskFields: Field[] = this.taskFields.slice()
    
    // 导出的工单字段列表
    let exportTaskFields: Field[] = []
    // 工单字段列表
    let taskFields: Field[] = []
    let addressFields: Field[] = []
    let linkmanFields: Field[] = []
    let productFields: Field[] = []
    
    // 过滤工单附件字段
    taskFields = CurrentTaskFields.filter(taskField => {
      return taskField.formType !== FieldTypeMappingEnum.Attachment
    })
    
    // 客户字段存在
    if (this.customerField) {
      // 客户配置
      const CustomerOption = this.customerField?.setting?.customerOption || {}
      // 开启地址
      if (CustomerOption.address) {
        addressFields = TaskAddressFields.slice()
      }
      // 开启联系人
      if (CustomerOption.linkman) {
        linkmanFields = TaskLinkmanFields.slice()
      }
      // 开启产品
      if (CustomerOption.product) {
        productFields = TaskProductFields.slice()
      }
    }
    
    // 字段名称
    let fieldName: string = ''
    
    taskFields.forEach((taskField: Field, index: number) => {
      // 工单字段名称
      fieldName = getFieldName(taskField)
      // 导出的工单字段列表添加当前工单字段
      exportTaskFields.push(taskField)
      
      // 工单编号字段
      if (fieldName === TaskFieldNameMappingEnum.TaskNo) {
        // 将工单类型字段插入到工单类型字段后面
        exportTaskFields.push(TaskTypeField)
      }
      
      // 客户字段
      if (fieldName === TaskFieldNameMappingEnum.Customer) {
        // 后端excel字段是固定位置 客户-联系人-电话-客户地址，所以需要前端按顺序来
        // 联系人字段存在则添加到导出的工单字段列表中
        if (linkmanFields.length) {
          linkmanFields.forEach(linkmanField => exportTaskFields.push(linkmanField))
        }
        // 地址字段存在则添加到导出的工单字段列表中
        if (addressFields.length) {
          addressFields.forEach(addressField => exportTaskFields.push(addressField))
        }
        // 产品字段存在则添加到导出的工单字段列表中
        if (linkmanFields.length) {
          productFields.forEach(productField => exportTaskFields.push(productField))
        }
      }
      
    })
    
    exportTaskFields = exportTaskFields.map((exportTaskField: Field) => {
      return {
        ...exportTaskField,
        label: exportTaskField.displayName,
        export: true
      }
    })

    if(exportTaskFields.some(item => item.formType === 'relationForm')){
      // 过滤掉关联表单的相关内容
      exportTaskFields = exportTaskFields.filter(val => val.formType !== 'relationForm')
    }
    // 基础版导出列的工单信息过滤产品字段
    if (this.isBasicEditionHideProduct) {
      exportTaskFields = exportTaskFields.filter(field => field.fieldName !== 'product')
    }
    
    // 工单信息存在服务商子表单的相关信息就过滤
    if(exportTaskFields.some(item => item.formType === 'serviceProviders')){
      exportTaskFields = exportTaskFields.filter(val => val.formType !== 'serviceProviders')
    }

    return exportTaskFields
  }
  
  /**
   * @description: 构建给导出列使用的工单回执字段列表
   * -- 抄的工单列表
   * @return {Field[]} 给导出列使用的工单回执字段列表
   */
  public buildExportColumnsOfTaskReceiptFields(): Field[] {
    // 当前工单类型的工单回执字段列表
    const CurrentTaskReceiptFields: Field[] = this.taskReceiptFields.slice()
    
    // 导出的工单回执字段列表
    const ExportTaskReceiptFields: Field[] = [
      ...TaskReceiptExportFields.slice(),
      ...CurrentTaskReceiptFields.filter((taskReceiptField: Field) => {
        // 过滤系统字段和附件类型字段 关联表单字段
        return (
          !isSystemFiled(taskReceiptField) 
          && taskReceiptField.formType !== FieldTypeMappingEnum.Attachment
          && taskReceiptField.formType !== FieldTypeMappingEnum.RelatedForm
        )
      })
    ]
    ExportTaskReceiptFields.forEach((item) => {
      if(item.formType === 'logistics'){
        if(item.fieldName.indexOf(LogisticsFieldNameMappingEnum.LogisticsNo) > -1){
          item.label = i18n.t('common.base.logisticsNo') as string
        }
    
         if(item.fieldName.indexOf(LogisticsFieldNameMappingEnum.LogisticsCompany) > -1){
          item.label = i18n.t('common.base.logisticsCompany') as string
        }
      }
    })

    return (
      ExportTaskReceiptFields.map(field => {
        field.export = true
        return field
      })
    )
  }
  
  /**
   * @description: 构建给导出列使用的工单附件组件字段列表
   * -- 抄的工单列表
   * @return {Field[]} 给导出列使用的工单回执字段列表
   */
  public buildExportColumnsOfTaskCardFields(): TaskExportGroup[] {
    // 当前工单类型的附加组件列表
    const CurrentTaskCardList: CardInfo[] = this.taskCardList.slice()
    
    // 导出的工单附加组件列表
    let exportTaskCardFields: TaskExportGroup[] = (
      CurrentTaskCardList
        .filter((taskCard: CardInfo) => {
          // 过滤仅可查看的附加组件
          return taskCard.canRead
        })
        .map((taskCard: CardInfo, index: number) => {
          // 构建导出工单附加组件列
          return this.buildExportTaskCardColum(taskCard, index)
        })
    )
    
    return exportTaskCardFields
  }
  
  /**
   * @description: 构建导出工单附加组件列
   * @param {CardInfo} taskCard 工单附加组件信息
   * @return {*}
   */  
  private buildExportTaskCardColum(taskCard: CardInfo, index: number): TaskExportGroup {
    // 工时记录 特殊处理
    if (taskCard?.specialfrom === ConstDataEnum.工时记录) {
      let sortedFields: Field[] = this.getTaskWorkTimeCardSortedFields(taskCard)
      let fieldName: string = ''
      
      // 过滤工时记录卡片附件字段
      sortedFields = sortedFields.filter((field: Field) => {
        return (
          !isAttachmentFiled(field)
        )
      })
      
      // 暂时不清楚用意
      sortedFields.forEach((field: Field) => {
        if (!field.map) {
          field.fieldName = `${taskCard.cardId}_${field.fieldName}`
        }
      })
      
      taskCard.fields = [
        ...sortedFields, 
        ...[
          // { displayName: TaskFieldDisplayNameMappingEnum.Distance, fieldName: `${taskCard.cardId}_${TaskFieldNameMappingEnum.Distance}`},
          { displayName: TaskFieldDisplayNameMappingEnum.Distance, fieldName: `${taskCard.cardId}_${TaskFieldNameMappingEnum.Distance}` },
          { displayName: TaskFieldDisplayNameMappingEnum.OperatorUser, fieldName: `${taskCard.cardId}_workingOperatorName` },
          { displayName: TaskFieldDisplayNameMappingEnum.OperatorTime, fieldName: `${taskCard.cardId}_workingOperateTime` }
        ]
      ]
      
    } else {
      taskCard.fields = [
        ...taskCard.fields, 
        ...[
          // 添加操作人，操作时间字段
          { displayName: TaskFieldDisplayNameMappingEnum.OperatorUser, fieldName: `cu_${taskCard.cardId}` }, 
          { displayName: TaskFieldDisplayNameMappingEnum.OperatorTime, fieldName: `ct_${taskCard.cardId}` }
        ]
      ]
    }
    
    const columns = (
      taskCard.fields
        .map((taskCardField: Field) => {
          return {
            export: taskCard.canRead,
            label: taskCardField.displayName,
            exportAlias: taskCardField.fieldName,
            cardIdExp: `cardId_${taskCard.cardId}`,
            ...taskCardField,
          };
        }).filter((taskCardField: Field) => {
          // 过滤附件类型字段
          return !isAttachmentFiled(taskCardField)
        })
    )
    
    return {
      value: `${TaskExportGroupValueEnum.Card}${index}`,
      label: `${TaskExportGroupTextEnum.Card}${taskCard?.cardName}`,
      inputType: taskCard.inputType,
      columns,
      cardId: `cardId_${taskCard.cardId}`
    }
  }
  
  private clearPageList() {
    this.page.list = []
    this.page.content = []
  }
  
  public exportData(type: string, list: any[] = []) {
    const export_list = this.exportTaskColumns
    
    if (type === 'cardFieldChecked') {
      let cardField: any[] = []
      export_list.filter((item, index) => {
        return index > 2
      }).forEach(v => {
        v.columns.forEach(item => {
          cardField.push(item)
        })
      })
      let cardIdArr:any[] = []
      let cardFieldArr = cardField.map(v => { 
        let bool = list.some(item => {
          // 附加组件需要加一个新的参数cardId_${cardId}, 暂时先这么改
          if( v.cardIdExp == item ) cardIdArr.push(v.cardIdExp)
          if (v.exportAlias) {
            return v.exportAlias === item
          } 
          return v.fieldName === item
          
        })
        if (bool) {
          return v.exportAlias ? v.exportAlias : v.fieldName
        }
      }).filter(item => {
        return item
      })
      cardIdArr = [...new Set(cardIdArr)];
      cardFieldArr = [...cardFieldArr, ...cardIdArr]
      return cardFieldArr
    }

    let xlistColumns: any[] = []
    export_list.forEach((xlist, i) => {
      if(xlist.value === type) xlistColumns = xlist.columns
    })

    return xlistColumns.map(v => {
      let bool = list.some(item => {
        if (v.exportAlias) {
          return v.exportAlias === item
        } 
        return v.fieldName === item
        
      })
      if (bool) {
        return v.exportAlias ? v.exportAlias : v.fieldName
      }
    }).filter(item => {
      return item
    })
  }
  
  /**
   * @description 构建导出参数
   * @return {TaskExportModel} 导出参数
   */
  public buildExportParams(checkedMap: TaskExportGroupChecked, ids: string[], exportOneRow?: boolean): TaskExportModel {
    return this.buildDefaultExportParams(checkedMap, ids, exportOneRow)
  }
  
  /**
   * @description 构建默认导出参数
   * @return {TaskExportModel} 默认导出参数
   */
  public buildDefaultExportParams(checkedMap: TaskExportGroupChecked, ids: string[], exportOneRow?: boolean): TaskExportModel {
    const { receiptChecked = [], systemChecked = [], taskChecked = [], expenseChecked = [] } = checkedMap
    // 登录用户信息
    const loginUser: LoginUser | null = this.rootWindowInitData?.user ?? null
    // 是否为导出全部
    const isExportAll: boolean = Boolean(!ids || !ids?.length)
    // 导出需要的搜索参数模型
    const exportSearchModel: Record<string, any> = {
      ...this.searchParams,
      ...this.advancedSearchModel,
      // 工单ids
      taskIds: isExportAll ? [] : this.selectedIds,
      // 当前登录人的团队列表
      tagIds: loginUser?.tagList?.map(tag => tag.id) || [],
      // 数据权限等级
      dataLevel: this.auth[AuthEnum.TASK_VIEW],
      // 租户id
      tenantId: loginUser?.tenantId,
      // 导出的数量
      exportTotal: isExportAll ? this.page.totalElements : this.selectedIds.length
    }
    
    // 导出参数
    let exportParams: TaskExportModel = {
      cardFieldChecked:   this.buildExportParamsOfTaskCardFieldChecked(checkedMap),
      checked:            this.buildExportParamsOfTaskChecked(taskChecked),
      data:               isExportAll ? '' : concat(this.selectedIds),
      exportOneRow:       Boolean(exportOneRow),
      exportSearchModel:  stringify(exportSearchModel),
      receiptChecked:     this.buildExportParamsOfTaskReceiptChecked(receiptChecked),
      sysChecked:         this.buildExportParamsOfTaskSystemChecked(systemChecked),
      typeId:             this.currentTaskType?.id || ''
    }

    console.log(exportParams, 'exportParams这里是导出的参数')
    
    if(expenseChecked && expenseChecked.length > 0) { // 审核结算-结算信息
      exportParams.expenseChecked = this.buildExportParamsOfTaskExpenseChecked(expenseChecked)
    }
    
    return exportParams
  }
  
  /**
   * @description 构建导出参数-工单字段选择的参数
   * @return {String[]} 工单字段字段选择的数据
   */
  private buildExportParamsOfTaskChecked(taskChecked: string[]): string {
    let exportTaskChecked: string[] = this.exportData('taskChecked', taskChecked)
    
    exportTaskChecked = exportTaskChecked
      .map((checkedKey: string) => {
        
        // 产品特殊处理 (添加产品编号字段)
        if (checkedKey === TaskFieldNameMappingEnum.Product) {
          checkedKey = concat([
            TaskFieldNameMappingEnum.Product,
            TaskFieldNameMappingEnum.ProductSN
          ])
        }
        
        return checkedKey
      })
    
    return concat(exportTaskChecked)
  }
  
  /**
   * @description 构建导出参数-工单回执字段选择的参数
   * @return {String[]} 工单回执字段字段选择的数据
   */
  private buildExportParamsOfTaskReceiptChecked(taskReceiptChecked: string[]): string {
    let exportTaskReceiptChecked: string[] = this.exportData('receiptChecked', taskReceiptChecked)
    
    exportTaskReceiptChecked = exportTaskReceiptChecked
      .map((checkedKey: string) => {
        
        // 如果选择【备件名称】列，则手动补全其他备件列数据
        if (checkedKey === TaskFieldExportNameMappingEnum.SparePartName) {
          checkedKey = concat([
            TaskFieldExportNameMappingEnum.SparePartName,
            TaskFieldExportNameMappingEnum.SparePartSN,
            TaskFieldExportNameMappingEnum.SparePartType,
            TaskFieldExportNameMappingEnum.SparePartNumber,
            TaskFieldExportNameMappingEnum.SparePartsPrice,
            TaskFieldExportNameMappingEnum.SpareStandard
          ])
        }
        
        // 如果选择【服务项目】列，则手动补全其他服务项目列数据
        if (checkedKey === TaskFieldExportNameMappingEnum.ServiceName) {
          checkedKey = concat([
            TaskFieldExportNameMappingEnum.ServiceName,
            TaskFieldExportNameMappingEnum.ServiceType,
            TaskFieldExportNameMappingEnum.ServiceNumber,
            TaskFieldExportNameMappingEnum.ServicePartsPrice
          ])
        }
        
        // 如果选择【费用信息】列，则手动补全其他结算费用列数据
        if (checkedKey === TaskFieldExportNameMappingEnum.BalanceTotal) {
          checkedKey = concat([
            TaskFieldExportNameMappingEnum.BalanceTotal,
            TaskFieldExportNameMappingEnum.BalanceDiscount,
            TaskFieldExportNameMappingEnum.BalanceSum
          ])
        }
        
        return checkedKey
      })
    
    return concat(exportTaskReceiptChecked)
  }
  
  /**
   * @description 构建导出参数-工单系统字段选择的参数
   * @return {String[]} 工单系统字段字段选择的数据
   */
  private buildExportParamsOfTaskSystemChecked(systemChecked: string[]): string {
    const exportTaskSystemChecked: string[] = this.exportData('systemChecked', systemChecked)
    
    return concat(exportTaskSystemChecked)
  }
  
  /**
   * @description 构建导出参数-工单系统字段选择的参数
   * @return {Sintrg[]} 工单系统字段字段选择的数据
   */
  private buildExportParamsOfTaskExpenseChecked(expenseChecked: string[]): string {
    const exportTaskExpenseChecked: string[] = this.exportData('expenseChecked', expenseChecked)
    
    return concat(exportTaskExpenseChecked)
  }
  
  /**
   * @description 构建导出参数-工单附件组件字段选择的参数
   * @return {String[]} 附件组件字段选择的数据
   */
  private buildExportParamsOfTaskCardFieldChecked(checkedMap: TaskExportGroupChecked): string {
    let cardFieldChecked: string[] = []
    
    for (let key in checkedMap) {
      if (key.indexOf(TaskExportGroupValueEnum.Card) !== -1) {
        cardFieldChecked = [...cardFieldChecked, ...checkedMap[key]]
        if(checkedMap[key].length > 0) {
          this.exportTaskColumns.forEach(item => {
            if(item.value == key) {
              cardFieldChecked = [...cardFieldChecked, item.cardId]
            }
          });
        }
      }
    }
    
    cardFieldChecked = cardFieldChecked.length ? this.exportData('cardFieldChecked', cardFieldChecked) : cardFieldChecked
    
    return concat(cardFieldChecked)
  }
  
  /**
   * @description 构建搜索基础参数
   * @param {Object} searchModelOfTaskView 你妹子的
   * @return {void} 搜索参数
   */
  private buildSearchParams(searchModelOfTaskView?: Record<string, any>): void {
    const params = this.buildSearchBaseParams()
    // 根据不同的创建视角状态构建 个人的搜索参数
    const taskViewPointSearchData = this.getTaskViewPointSearchData()
    
    Log.info(params, 'params', this.buildSearchParams.name)
    
    // 是否有 视图上的搜索条件 searchModel
    // if (isObject(searchModelOfTaskView)) {
    //   this.buildSearchParamsWithSearchModel(
    //     searchModelOfTaskView as Record<string, any>,
    //     params,
    //     taskViewPointSearchData
    //   )
    // } else {
    this.buildSearchParamsWithSearchParams(params, taskViewPointSearchData)
    // }
    
  }
  
  /** 
   * @description 根据 现有的搜索参数 构建搜索参数
   * 都是抄的之前的
  */
  public buildSearchParamsWithSearchParams(params: TaskSearchListModel, mySearchData: {
    createUser?: string,
    executor?: string,
    synergyId?: string
  }) {
      // 排序条件
      const sorts: EsSort[] = this.buildSortsForSearch(params)
      // 地址数据
      const city: City = this.buildCityForSearch(params)
      const { cusCountry = '', cusProvince = '', cusCity = '', cusDist = '' } = city
      // 系统字段查询条件
      // const { systemConditions = [] } = params
      // 自定义字段查询条件
      // const conditions = params.conditions || []
      // 工单 各流程 时间数据
      const {
        acceptTimeStart, acceptTimeEnd, allotTimeStart, allotTimeEnd, balanceTimeStart, balanceTimeEnd,
        closeTimeStart, closeTimeEnd, completeTimeStart, completeTimeEnd, createTimeStart, createTimeEnd,
        planTimeStart, planTimeEnd, reviewTimeStart, reviewTimeEnd, startTimeStart, startTimeEnd,
        updateTimeStart, updateTimeEnd, planStartTimeStart, planStartTimeEnd, planEndTimeStart, planEndTimeEnd,evaluationTimeStart,evaluationTimeEnd,
      } = this.buildTimeForSearch(params)
      
      // 曾转派
      let onceReallot: number | null = taskOnceFieldValueConvert(params.onceReallot)
      // 曾打印
      let oncePrinted: number | null = taskOnceFieldValueConvert(params.oncePrinted)
      // 是否审批中
      let inApprove: number | null = taskApproveValueConvert(params.inApprove)
      
      // TODO: refactoring
      const SearchParams: EsTaskSearchInput = {
          cusCountry,
          cusProvince,
          cusCity,
          cusDist,
          
          // conditions: [...conditions],
          
          customerId: params.customerId,
          customerLinkman: params.tlmName || '',
          cusAddress: params.cusAddress,
          productId: params.productId,
          description: params.description,
          
          createTimeStart,
          createTimeEnd,
          planTimeStart,
          planTimeEnd,
          allotTimeStart,
          allotTimeEnd,
          acceptTimeStart,
          acceptTimeEnd,
          startTimeStart,
          startTimeEnd,
          completeTimeStart,
          completeTimeEnd,
          updateTimeStart,
          updateTimeEnd,
          reviewTimeStart,
          reviewTimeEnd,
          evaluationTimeStart,
          evaluationTimeEnd,
          balanceTimeStart,
          balanceTimeEnd,
          closeTimeStart,
          closeTimeEnd,
          planStartTimeStart, 
          planStartTimeEnd, 
          planEndTimeStart, 
          planEndTimeEnd,
          balanceUser: params.balanceUser,
          reviewUser: params.reviewUser,
          degree: params.degree,
          
          onceReallot,
          oncePrinted,
          inApprove,
          
          sorts,
          
          templateName: params.templateName,
          keyword: params.keyword,
          page: params.page,
          pageSize: params.pageSize,
          templateId: this.currentTaskType?.id,
          
          /* start 以下是支持多选的 */
          serviceTypes: params.serviceTypes,
          serviceContents: params.serviceContents,
          levels: params.levels,
          
          searchStateList: params.states && params.states.map(stateName => TaskStateEnum.getValue(stateName)),
          allotTypes: this.getAllotTypesForSearch(params.allotTypeStrs),
          flags: params.onceExceptions && params.onceExceptions.map(exception => FlagConvertMap[exception]).filter(exception => Boolean(exception)),
          
          createUserIds: this.getUserIdsForSearch(params.createUser) || getUserIdsForSearch(mySearchData.createUser, params, 'createUser'),
          executorUserIds: this.getUserIdsForSearch(params.executor) || getUserIdsForSearch(mySearchData.executor, params, 'executor'),
          synergyUserIds: this.getUserIdsForSearch(params.synergyId) || getUserIdsForSearch(mySearchData.synergyId, params, 'synergyId'),
          allotUserIds: getUserIdsForSearch(null, params, 'allotUser'),
          
          payTypes: params.paymentMethods,
          searchTagIds: params.tags && params.tags.map(({ id }) => id),
          /* end 以上是支持多选的 */
          
          // systemConditions
      }
      
      // 工单搜索分类型
      if (this.keywordSelect) {
        SearchParams.searchCondition = this.keywordSelect
      }
      
      this.searchParams = { ...this.searchParams, ...SearchParams }
      
      Log.info(this.searchParams, 'searchParams', this.buildSearchParamsWithSearchParams.name)
  }
  
  /** 
   * @description 根据视图上的searchModel构建搜索参数
  */
  public buildSearchParamsWithSearchModel(searchModelOfTaskView: Record<string, any>, params: TaskSearchListModel, mySearchData: {
    createUser?: string,
    executor?: string,
    synergyId?: string
  }) {
    // TODO: 清空高级搜索的数据
    this.BaseSearchPanelComponent?.resetParams()
    // 清空搜索关键字
    this.params.keyword = ''
    // 拷贝数据
    let searchModel: Record<string, any> = _.cloneDeep(searchModelOfTaskView)
    
    // 页码大小
    searchModel.page = params.page
    // 创建时间
    searchModel.createTimeStart = this.getDateOfCutTimeString(searchModel.createTimeStart || searchModel.timeStart, undefined)
    searchModel.createTimeEnd = this.getDateOfCutTimeString(searchModel.createTimeEnd || searchModel.timeEnd, undefined)
    // 计划时间
    searchModel.planTimeStart = this.getDateOfCutTimeString(searchModel.planTimeStart, undefined)
    searchModel.planTimeEnd = this.getDateOfCutTimeString(searchModel.planTimeEnd, undefined)
    // 派单时间
    searchModel.allotTimeStart = this.getDateOfCutTimeString(searchModel.allotTimeStart, undefined)
    searchModel.allotTimeEnd = this.getDateOfCutTimeString(searchModel.allotTimeEnd, undefined)
    // 接收时间
    searchModel.acceptTimeStart = this.getDateOfCutTimeString(searchModel.acceptTimeStart, undefined)
    searchModel.acceptTimeEnd = this.getDateOfCutTimeString(searchModel.acceptTimeEnd, undefined)
    // 开始时间
    searchModel.startTimeStart = this.getDateOfCutTimeString(searchModel.startTimeStart, undefined)
    searchModel.startTimeEnd = this.getDateOfCutTimeString(searchModel.startTimeEnd, undefined)
    // 完成时间
    searchModel.completeTimeStart = this.getDateOfCutTimeString(searchModel.completeTimeStart, undefined)
    searchModel.completeTimeEnd = this.getDateOfCutTimeString(searchModel.completeTimeEnd, undefined)
    // 更新时间
    searchModel.updateTimeStart = this.getDateOfCutTimeString(searchModel.updateTimeStart, undefined)
    searchModel.updateTimeEnd = this.getDateOfCutTimeString(searchModel.updateTimeEnd, undefined)
    // 更新时间
    searchModel.reviewTimeStart = this.getDateOfCutTimeString(searchModel.reviewTimeStart, undefined)
    searchModel.reviewTimeEnd = this.getDateOfCutTimeString(searchModel.reviewTimeEnd, undefined)
    // 评价时间
    searchModel.evaluationTimeStart = this.getDateOfCutTimeString(searchModel.evaluationTimeStart, undefined)
    searchModel.evaluationTimeEnd = this.getDateOfCutTimeString(searchModel.evaluationTimeEnd, undefined)
    // 结算时间
    searchModel.balanceTimeStart = this.getDateOfCutTimeString(searchModel.balanceTimeStart, undefined)
    searchModel.balanceTimeEnd = this.getDateOfCutTimeString(searchModel.balanceTimeEnd, undefined)
    // 结算时间
    searchModel.closeTimeStart = this.getDateOfCutTimeString(searchModel.closeTimeStart, undefined)
    searchModel.closeTimeEnd = this.getDateOfCutTimeString(searchModel.closeTimeEnd, undefined)
    // 计划开始时间
    searchModel.planStartTimeStart = this.getDateOfCutTimeString(searchModel.planStartTimeStart, undefined)
    searchModel.planStartTimeEnd = this.getDateOfCutTimeString(searchModel.planStartTimeEnd, undefined)
    // 计划完成时间
    searchModel.planEndTimeStart = this.getDateOfCutTimeString(searchModel.planEndTimeStart, undefined)
    searchModel.planEndTimeEnd = this.getDateOfCutTimeString(searchModel.planEndTimeEnd, undefined)
    // 工单类型Id
    searchModel.templateId = this.currentTaskType?.id
    
    this.searchParams = { ...searchModel, ...mySearchData }
    
    Log.info(this.searchParams, 'searchParams', this.buildSearchParamsWithSearchModel.name)
  }
  
  /** 
   * @description 构建排序数据
  */
  public buildSortsForSearch(params: TaskSearchListModel): EsSort[] {
    if (!params?.orderDetail) return []
    
    let { column = '', isSystem, sequence } = params.orderDetail
    
    if (!column) return []
    
    // 排序条件
    let sorts: EsSort[] = []
    // 排序字段
    const SortedField = getFieldWithFieldName(this.taskListFields, column) || { isSystem: null }
    
    // 是否为需要转换的字段
    const IsConvertedField = Object.keys(UserNameConvertMap).includes(column)
    
    if (
      column == TaskFieldNameMappingEnum.UpdateTime 
      || column == TaskFieldNameMappingEnum.CreateTime
      || IsConvertedField
    ) {
      isSystem = true
    } else {
      isSystem = Boolean(SortedField?.isSystem)
    }
    
    if (IsConvertedField) {
      column = UserNameConvertMap[column]
    }
    
    sorts = [
      {
        property: isSystem ? column : `attribute.${column}`,
        direction: sequence,
      }
    ]
    
    return sorts
  }
  
  /** 
   * @description 构建地址数据
  */
  public buildCityForSearch(params: TaskSearchListModel): City {
    // 城市
    let cityData: City = {}
    
    // FIXME: 日，改名 草
    if (params?.productAddress) {
      const { country, province, city, dist } = params.productAddress
      cityData = {
        cusProvince: province,
        cusCity: city,
        cusDist: dist
      }

      country && (cityData.cusCountry = country);
    }
    
    return cityData
  }
  
  /** 
   * @description 构建搜索时间数据
  */
  public buildTimeForSearch(params: TaskSearchListModel): Record<string, string | Date | null> {
    // 接受时间
    const acceptTimeStart = this.getDateOfCutTimeString(params.acceptTime, true, true)
    const acceptTimeEnd = this.getDateOfCutTimeString(params.acceptTime, false, true)
    // 派单时间
    const allotTimeStart = this.getDateOfCutTimeString(params.allotTime, true, true)
    const allotTimeEnd = this.getDateOfCutTimeString(params.allotTime, false, true)
    // 结算时间
    const balanceTimeStart = this.getDateOfCutTimeString(params.balanceTime, true, true)
    const balanceTimeEnd = this.getDateOfCutTimeString(params.balanceTime, false, true)
    // 关闭时间
    const closeTimeStart = this.getDateOfCutTimeString(params.closeTime, true, true)
    const closeTimeEnd = this.getDateOfCutTimeString(params.closeTime, false, true)
    // 完成时间
    const completeTimeStart = this.getDateOfCutTimeString(params.completeTime, true, true)
    const completeTimeEnd = this.getDateOfCutTimeString(params.completeTime, false, true)
    // 创建时间
    const createTimeStart = this.getDateOfCutTimeString(params.createTime, true, true)
    const createTimeEnd = this.getDateOfCutTimeString(params.createTime, false, true)
    // 计划时间
    const planTimeStart = this.getDateOfCutTimeString(params.planTime, true, true)
    const planTimeEnd = this.getDateOfCutTimeString(params.planTime, false, true)
     // 计划开始时间
    const planStartTimeStart = this.getDateOfCutTimeString(params.planStartTime, true, true)
    const planStartTimeEnd = this.getDateOfCutTimeString(params.planStartTime, false, true)
      // 计划完成时间
    const planEndTimeStart = this.getDateOfCutTimeString(params.planEndTime, true, true)
    const planEndTimeEnd = this.getDateOfCutTimeString(params.planEndTime, false, true)
    // 回访时间
    const reviewTimeStart = this.getDateOfCutTimeString(params.reviewTime, true, true)
    const reviewTimeEnd = this.getDateOfCutTimeString(params.reviewTime, false, true)
    // 评价时间
    const evaluationTimeStart= this.getDateOfCutTimeString(params.evaluationTime, true, true)
    const evaluationTimeEnd = this.getDateOfCutTimeString(params.evaluationTime, false, true)

    // 开始时间
    const startTimeStart = this.getDateOfCutTimeString(params.startTime, true, true)
    const startTimeEnd = this.getDateOfCutTimeString(params.startTime, false, true)
    // 更新时间
    const updateTimeStart = this.getDateOfCutTimeString(params.updateTime, true, true)
    const updateTimeEnd = this.getDateOfCutTimeString(params.updateTime, false, true)
    
    return {
      acceptTimeStart, acceptTimeEnd, allotTimeStart, allotTimeEnd, balanceTimeStart, balanceTimeEnd,
      closeTimeStart, closeTimeEnd, completeTimeStart, completeTimeEnd, createTimeStart, createTimeEnd,
      planTimeStart, planTimeEnd, reviewTimeStart, reviewTimeEnd, evaluationTimeStart, evaluationTimeEnd,startTimeStart, startTimeEnd,
      updateTimeStart, updateTimeEnd, planStartTimeStart, planStartTimeEnd, planEndTimeStart, planEndTimeEnd
    }
    
  }
  
  /**
   * @description 构建搜索基础参数
   * @return {Object} 搜索参数
   */
  private buildSearchBaseParams(): TaskSearchListModel {
    const Params = { ...this.searchParams, ...this.params }
    let searchParams = {
      keyword: Params.keyword,
      pageSize: Params.pageSize,
      page: Params.pageNum,
      typeId: this.currentTaskType?.id,
      orderDetail: null,
      createUser: undefined,
      ...this.advancedSearchModel,
    }
    
    // 搜索详细信息不为空
    if (!isEmpty(Params?.orderDetail)) {
      searchParams.orderDetail = Params.orderDetail
    }
    
    // 更多搜索条条件不为空
    if (!isEmpty(Params.moreConditions)) {
      searchParams = {
        ...searchParams,
        ...Params.moreConditions,
        createUser: searchParams.createUser || Params.moreConditions.createUser || Params.moreConditions.createUserName
      }
    }
    
    return searchParams
  }
  
  public buildAdvancedColumnsWithCustomer(): Field[] {
    let addressFields: Field[] = []
    let linkmanFields: Field[] = []
    let productFields: Field[] = []
    
    // 不存在客户字段
    if (!this.customerField) return []
    
    // 客户配置
    const CustomerOption: Record<string, boolean | undefined> = this.customerField?.setting?.customerOption || {}
    // 开启地址
    if (CustomerOption.address) {
      addressFields = TaskAdvancedAddressFields.slice()
    }
    // 开启联系人
    if (CustomerOption.linkman) {
      linkmanFields = [TaskLinkmanFields[0]]
    }
    // 开启产品
    if (CustomerOption.product) {
      productFields = TaskProductFields.slice()
    }
    
    return addressFields.concat(linkmanFields).concat(productFields)
  }
  
  public buildAdvancedColumnsWithTask(): Field[] {
    return (
      this.taskFields
        .filter(taskField => {
          // 过滤非系统字段和附件字段和工单编号字段
          return isSystemFiled(taskField) && !isAttachmentFiled(taskField) && !isTaskNoField(taskField)
        })
        .map(taskField => {
          if (isPlanTimeField(taskField)) {
            taskField.formType = FieldTypeMappingEnum.DateTime
            taskField.isNull = 1
          }
          
          return taskField
        })
    )
  }
  
  /**
   * @description 构建高级搜索列
   */
  public buildAdvancedColumns() {
    const InquireFields: Field[] = Inquire.slice() as any[]
    
    this.advanceSearchColumns = [
      ...this.buildAdvancedColumnsWithTask(),
      ...this.buildAdvancedColumnsWithCustomer(),
      ...InquireFields,
      ...this.abnormalFields
    ]

    console.log(this.advanceSearchColumns, 'advanceSearchColumns所有的')
  }
  
  /**
   * @description: 构建删除工单参数
   * @return {String}
   */  
  public buildDeleteParams(): Array<string> {
    return this.selectedIds
    // return (
    //   concat(this.selectedIds.map(id => `taskIds=${id}`), '&')
    // )
  }
  
  /**
   * @description: 删除事件
   * @return {void}
   */  
  public async deleteHandler(): Promise<void | boolean> {
    // @ts-ignore
    this.$track.clickStat(this.$track.formatParams('DELETE'));

    const validated = this.selectedTaskDataValidate()
    if (!validated) return
    
    /** 
     * 如果工单为未完成状态，则需要判断工单是否曾回退，而且在最后一次完成时是否使用了备件
     * 如果使用了备件，需要提示
    */
    const params = this.buildDeleteParams()
    
    try {
      const withPartResult = await withPart(params)
      // 获取判断备件信息失败
      if (!withPartResult.succ) {
        return Platform.alert(withPartResult.message)
      }
      
      // 获取删除工单提示
      const confirmMessage = this.getTaskDeleteConfirmMessage(withPartResult)
      const confirm = await Platform.confirm(confirmMessage)
      if (!confirm) return
      
      // 删除工单
      const deleteTaskResult = await deleteTask(this.selectedIds)
      if (!deleteTaskResult.success) {
        return Platform.alert(deleteTaskResult?.message || '')
      }
      
      Platform.alert(DELETE_SUCCESS_MESSAGE)
      this.BizTableComponent?.outsideClearSelection()
      this.multipleSelection = []
      this.refresh()
      
    } catch (error) {
      Log.error(error, this.deleteHandler.name)
    }
  }
  
  /**
   * @description: 获取表格列表数据
   * @param {Record} advancedSearchParams
   * @return {void}
   */  
  public fetchTableListData(): void {
    const params = {
      ...this.searchParams,
      ...this.advancedSearchModel,
    }
    this.fetchTaskList(params, search)
  }
  
  /**
   * @description: 获取工单列表数据
   * @param {Record} params 参数
   * @return {void}
   */  
  public fetchTaskList(params: TaskSearchListModel, searchFunction: Function = search): void {
    this.loading = true
    
    // 后端操作es没那么快，需要延迟一点时间才能获取正确的数据
    setTimeout(() => {
      searchFunction(params)
      .then((res: getTaskSearchListResult) => {
        // @ts-ignore
        this.page = res?.result || {}
          if (this.multipleSelection?.length) {
            // @ts-ignore
            // 调用重新渲染表格的方法，把选中数据的选中状态重新渲染到表格上
            this.BizTableComponent.reRenderTable()
          }
      })
      .catch((err: any) => {
        console.error(err)
      })
      .finally(() => {
        this.loading = false
      })
    }, 1500)
  }
  
  /** 
   * @description 获取工单类型 
  */
  public fetchTaskTypesMap() {
    return (
      getTaskTypesMap().then((data: getTaskTypesResult) => {
        const isSuccess = data.success
        if (!isSuccess) return
        
        const taskTypeSimpleList: TaskTypeSimple[] = data?.result || []
        this.taskTypes = taskTypeSimpleList.map(taskTypeSimple => TaskTypeSimple.toTaskType(taskTypeSimple))
        // key : 工单类型id(string) -> value: TaskType
        this.taskTypesMap = (
          this.taskTypes
            .reduce((acc: Record<string, TaskType>, currentTaskType: TaskType) => {
              acc[currentTaskType.templateId] = currentTaskType
              return acc
            }, {})
        )
      }).catch(err => {
        console.error(err)
      })
    )
  }
  
  /** 
   * @description 查询工单配置
   * @return {Promise<void>}
  */
  public fetchTaskConfig(): Promise<void> {
    return (
      getTaskConfig()
      .then((result: getTaskConfigResult) => {
        this.taskConfig = result?.taskConfig || null
      })
      .catch(error => {
        Log.error(error, this.fetchTaskConfig.name)
      })
    )
  }
  
  /**
   * @description 获取工单字段列表
   * @return {Promise}
   */
  async fetchTaskFields(): Promise<Field[]> {
    let params = {
      templateId: this.currentTaskType?.id || '',
      tableName: TableNameEnum.Task,
      isFromSetting: false
    }
    
    let result: Field[] = []
    
    try {
      result = await getTaskTemplateFields(params)
    } catch (error) {
      result = []
      Log.error(error, this.fetchTaskFields.name)
    }
    
    result.forEach((field: Field) => {
      field.group = TableNameEnum.Task
      field.label = field.displayName
      field.field = field.fieldName
      if(isCurrencyField(field)) {
        field.exportAlias = `${field.fieldName}_amount_number`
      }
    })

    this.taskFields = smoothLogisticsField(result || [])
    
    return result
  }
  
  /**
   * @description 获取工单回执字段列表
   * @return {Promise}
   */
  async fetchTaskReceiptFields() {
    let params = {
      templateId: this.currentTaskType?.id || '',
      tableName: TableNameEnum.TaskReceipt,
      isFromSetting: false
    }
    
    let result: Field[] = []
    
    try {
      result = await getTaskTemplateFields(params)
    } catch (error) {
      result = []
      console.warn('Caused: fetchTaskReceiptFields error', error)
    }
    
    result.forEach((field: Field) => {
      field.group = TableNameEnum.TaskReceipt,
      field.label = field.displayName
      field.field = field.fieldName
      if(isCurrencyField(field)) {
        field.exportAlias = `${field.fieldName}_amount_number`
      }
    })
    
    this.taskReceiptFields = smoothLogisticsField(result || [])

    return result
  }
  
  /**
   * @description 获取满意度字段列表
   * @return {Promise}
   */
  async fetchSatisfactionFields() {
    if(!this.rootWindowInitData?.customerSatisfaction){
      return []
    }
    let params = {
      templateId: this.currentTaskType?.id || ''
    }
    
    let result: Field[] = []
    
    try {
      let res = await getSatisfactionFields(params);
      result = res.result;
    } catch (error) {
      result = []
      console.warn('Caused: fetchSatisfactionFields error', error)
    }
    
    result.forEach((field: Field) => {
      field.group = TableNameEnum.Task,
      field.label = field.displayName
      field.field = field.fieldName
      field.tableName = 'satisfaction'
    })
    
    this.satisfactionFields = result
    return result
  }
  
  /**
   * @description 获取工单附加组件字段列表
   * @return {Promise}
   */
  async fetchTaskCardFields(): Promise<CardInfo[]> {
    let params = {
      typeId: this.currentTaskType?.id || '',
    }
    
    let result: CardInfo[] = []
    
    try {
      result = await getCardDetailList(params)
    } catch (error) {
      result = []
      Log.error(error, this.fetchTaskCardFields.name)
    }
    
    this.taskCardList = result
    
    return result
  }
  
  /**
   * @description 获取用户开启的配置节点 以及工单搜索范围 和 异常原因字段值
   * @return {void}
   */  
  public fetchTurnOnTaskExceptionNodeInfo(): Promise<void> {
    return (
      getTurnOnTaskExceptionNodeInfo()
        .then((data: getTurnOnTaskExceptionNodeInfoResult) => {
          if (!data.success) return
          
          // 异常数据
          this.abnormalData = data?.result || new TaskException()
          
          // 异常原因列表
          const { taskExceptionReasonList = [] } = data?.result
          
          mergeFieldsWithProperty<Field, TaskExceptionReason, void>(
            this.abnormalFields, 
            taskExceptionReasonList,
            (abnormalField: Field, taskExceptionReasonItem: TaskExceptionReason) => {
              // 设置setting属性
              if (!abnormalField?.setting) {
                abnormalField.setting = {}
              }
              
              // 设置支持异常原因单选
              abnormalField.setting.isMulti = false
              abnormalField.setting.dataSource = taskExceptionReasonItem?.exceptionReason || []
            }
          )
          
        })
        .catch(error => {
          Log.error(error, this.fetchTurnOnTaskExceptionNodeInfo.name)
        })
    )
  }
  
  /**
   * @description: 获取高级搜索字段列表
   * @param {BizListViewTask} vm 当前实例
   * @return {Field[]} 高级搜索字段列表
   */  
  public getAdvancedFields(vm: BizListViewTask): Field[] {
    return []
  }
  
  /**
   * @description: 获取表格列字段列表
   * @param {BizListViewTask} vm 当前实例
   * @return {Field[]} 表格列字段列表
   */  
  public getColumnFields(vm: BizListViewTask): Field[] {
    return []
  }
  
  /**
   * @description 获取工单删除确认提示
   * @param {getTaskFilterWithPartResult} withPartResult 
   * @return {String}
   */  
  public getTaskDeleteConfirmMessage(withPartResult: getTaskFilterWithPartResult): string {
    // 默认删除提示
    let confirmMessage: string = BATCH_DELETE_TASK_MASSAGE
    
    // 错误处理
    if (withPartResult?.status) {
      return BatchDeleteTaskErrorMessage(withPartResult?.message || '')
    }
    
    // 未出错，但是某些工单以添加备件
    let partData: string[] = withPartResult?.data || []
    if (!withPartResult?.status && !isEmpty(partData)) {
      return t('common.base.tip.delTaskWithSparePart', { number: this.getTaskDeleteConfirmMessageForPart(partData) })
    }
    
    return confirmMessage
  }
  
  public getTaskDeleteConfirmMessageForPart(partData: string[]): string {
    // 最多显示5条工单信息
    const maxIdsLength: number = 5
    
    if (partData.length <= maxIdsLength) {
      return concat(partData, '、')
    } 
    
    const taskIds: string[] = []
    
    for (let i = 0; i < maxIdsLength; i++) {
      taskIds.push(taskIds[i])
    }
    
    return `${concat(taskIds, '、')}等${partData.length}个`
  }
  
  /** 
   * @description 切割时间字符串获得时间
   * @param {String} time example: 2020/10/08-2020/11/10
   * @param {Boolean} isStartTime 是否只需要开始时间 (!!!此参数不要加默认值)
  */
  public getDateOfCutTimeString(time: string | undefined, isStartTime: boolean | undefined = true, isRequiredDate: boolean = true): Date | string | null {
    if (!time) {
      Log.warn('Caused: The Function cutTimeString parameter time is empty', this.getDateOfCutTimeString.name)
      return null
    }
    let date: Date | string | null = time
    
    try {
      // isStartTime 参数不传 默认undefined, 则直接用time生成时间
      if (isUndefined(isStartTime)) return safeNewDate(date) 
      
      let dates: string[] = time.split('-')
      let startDate: string = dates[0] || ''
      let endDate: string = dates[1] || ''
      
      date = isStartTime ? `${startDate} ${StartDateHMS}` : `${endDate} ${EndDateHMS}`
      date = isRequiredDate ? safeNewDate(date) : date
      
    } catch (error) {
      date = null
      Log.error(error, this.getDateOfCutTimeString.name)
    }
    
    return date
  }
  
  /** 
   * @description 获取的创建视角搜索数据
   * -- 抄的之前的
  */
  private getTaskViewPointSearchData(): {
    createUser?: string,
    executor?: string,
    synergyId?: string
  } {
    const { selectViewPointId, initData } = this
    let mySearch = {}
    
    // 根据当前创建视角的值 处理搜索条件的某些字段
    switch (selectViewPointId) {
      case TaskViewPointIdEnum.All: {
        mySearch = {}
        this.searchParams.createUser = ''
        this.searchParams.executor = ''
        this.searchParams.synergyId = ''
        break
      }
      case TaskViewPointIdEnum.Create: {
        mySearch = { createUser: initData.currentUserId }
        this.searchParams.createUser = ''
        break
      }
      case TaskViewPointIdEnum.Execute: {
        mySearch = { executor: initData.currentUserId }
        this.searchParams.executor = ''
        break
      }
      case TaskViewPointIdEnum.Synergy: {
        mySearch = { executor: initData.currentUserId }
        this.searchParams.synergyId = ''
        break
      }
      default: {
        break
      }
    }
    
    return mySearch
  }
  
  /**
   * @description: 获取工时记录卡片排序后的字段列表
   * @param {CardInfo} taskCard 工时记录卡片
   * @return {Field[]} 排序后的字段列表
   */  
  private getTaskWorkTimeCardSortedFields(taskCard: CardInfo): Field[] {
    // 工时开始位置字段
    const startAddress: Field = {
      displayName: TaskFieldDisplayNameMappingEnum.StartAddress,
      fieldName: TaskFieldNameMappingEnum.StartAddress
    }
    // 工时结束位置字段
    const endAddressField: Field = {
      displayName: TaskFieldDisplayNameMappingEnum.EndAddress,
      fieldName: TaskFieldNameMappingEnum.EndAddress
    }
    // 原工单卡片字段列表 拼接 开始/结束 位置字段
    const originTaskCardFields: Field[] = (taskCard?.fields || []).concat([startAddress, endAddressField]).slice()
    // 排序的字段名称列表
    const sortFieldNames: string[] = [
      TaskFieldNameMappingEnum.StartTime,
      TaskFieldNameMappingEnum.StartAddress,
      TaskFieldNameMappingEnum.EndTime,
      TaskFieldNameMappingEnum.EndAddress,
      TaskFieldNameMappingEnum.UsedTimeType
    ]
    
    return sortFields(originTaskCardFields, sortFieldNames)
  }
  
  public getUserIdsForSearch(data: any): any[] | null {
    if (isString(data)) return [data]
    if (isArray(data)) return data
    
    return null
  }

  public getAllotTypesForSearch(allotTypeStrs: any) {
    const allotType =  allotTypeStrs && allotTypeStrs.map((type: string | number) => AllotTypeConvertMap[type])
    return allotType && allotType.includes(0) ? [] : allotType  // 派单方式选择全部时，传个空数组
  }
  
  /**
   * @description: 初始化工单类型所有字段
   * 工单类型变化之后的事件
   * 1. 获取工单类型字段
   * 2. 获取工单类型回执字段
   * 3. 获取工单类型附加卡片信息
   * 4. 获取用户开启的配置节点 以及工单搜索范围 和 异常原因字段值
   * 5. 构建高级搜索列
   * 6. 构建导出列
   * @return {void}
   */  
  public async initializeTaskTypeAllFields(): Promise<void> {
    // 初始化之前需要reset回执字段，否则fetchTaskFields后onTaskFieldsChangedHandler时审核结算的getColumnFields方法获取的回执字段还是旧值
    this.taskReceiptFields = []
    
    // 获取工单类型字段
    await this.fetchTaskFields()
    // 获取工单类型回执字段
    await this.fetchTaskReceiptFields()
    // 获取工单类型附加卡片信息
    await this.fetchTaskCardFields()
    // 获取用户开启的配置节点 以及工单搜索范围 和 异常原因字段值
    await this.fetchTurnOnTaskExceptionNodeInfo()
    // 构建高级搜索列
    this.buildAdvancedColumns()
    // 构建导出列
    this.buildExportColumns()
  }
  
  /**
   * @description 合并本地缓存列数据至当前实例的列数据
   */
  async mergeLocalStorageColumnsToColumns() {
    const storageColumns = await this.getDataWithStorage(this.taskTypeColumnsStorageKey, [])
    if (isEmpty(storageColumns)) return
    
    this.columns = mergeFieldsWithProperty<Column, Field, Column>(
      this.columns,
      storageColumns,
      (column, storageDataColumn) => {
        // 列名不匹配则返回
        if (getFieldName(column) !== getFieldName(storageDataColumn)) {
          return column
        }
        
        // 覆盖列显示状态
        // column.show = Boolean(storageDataColumn.show) // 因为有show = 'important'的存在，所以不能直接Boolean
        column.show = storageDataColumn.show
        // 覆盖宽度数据
        if (storageDataColumn?.width) {
          column.width = storageDataColumn.width
        }
        column.fixLeft = storageDataColumn.fixLeft && 'left'
        
        return column
      }
    )
    // column没有该字段 缓存里有 合并方法会返回undefined 这里把undefined过滤掉
    this.columns = this.columns.filter(Boolean)
    
    this.reRenderTable()
  }
  
  /**
   * @description: 打开导出面板
   * @param {string} exportIds 导出的ids列表
   * @param {string} fieldName 导出的文件名
   * @return {void}
   */  
  public openExportPanel(exportIds: string[], fieldName: string): void {
    // @ts-ignore
    this.BaseExportComponent?.open(exportIds, fieldName)
  }
  
  public refresh() {
    this.searchParams.pageNum = 1
    this.search()
  }
  
  /**
   * @description: 选择数据验证
   * @return {void}
   */  
  public selectedTaskDataValidate(selectedIds: string[] = []): boolean {
    let validated = true
    // 未选择数据错误提示
    if (!this.selectedIds.length && !selectedIds.length) {
      validated = false
      Platform.alert(PLEASE_SELECT_DATA_MESSAGE)
    }
    
    return validated
  }
  
  /**
   * @description: 搜索
   * @return {void}
   */
  public search(): void {
    Log.succ(Log.Start, this.search.name)
    this.buildSearchParams()
    this.templateNameConversion()
    this.fetchTableListData()
  }
  
  /**
   * @description: 把工单类型值name转换成id
   * @return {void}
   */
  public templateNameConversion(): void {}
  
  /**
   * @description: 切换高级搜索面板
   * @param {boolean} toggle 切换的状态
   * @return {void}
   */  
  public toggleAdvancedSearchPanel(toggle: boolean = true): void {
    if (!toggle) {
      // @ts-ignore
      return this.TaskSearchPanelComponent?.hide()
    }
    
    // @ts-ignore
    this.TaskSearchPanelComponent?.mergeTaskFields(this.taskFields.concat(this.taskReceiptFields))
    // @ts-ignore
    this.TaskSearchPanelComponent?.open()
  }
  
  /**
   * @description: 切换选择列弹窗
   * @param {boolean} toggle 切换的状态
   * @return {void}
   */
  public toggleSelectColumnsDialog(toggle: boolean = true) {
    // @ts-ignore
    this.$track.clickStat(this.$track.formatParams('SELECT_COLUMN'));

    this.visibleSelectColumnDialog = toggle
    if (toggle) {
      this.BizSelectColumnComponent?.open(this.columns, this.currentTaskType)
    }
  }
  
  
  /**
   * @description 保存更新的选择列信息 
  */
  public saveColumnStatus(value: { type: string, data: any[] }) {
    let columns = value.data || []
    const NewColumnMap = columns.reduce(
      (acc, col) => (acc[col.field] = col) && acc,
      {}
    )
    // 列对象
    const OldColumnsMap: Record<string, Column> = fieldArrayToObject<Column>(this.columns)
    let oldColumn: Column
    let newColumn: Column
    let field: string
    this.columns = columns.map((column: Column) => {
      field = column.field || ''
      oldColumn = OldColumnsMap[field] || {}
      newColumn = NewColumnMap[field] || {}
      
      oldColumn.show = newColumn.show
      oldColumn.width = newColumn.width
      oldColumn.fixLeft = newColumn.fixLeft
      
      return oldColumn
    })
    
    const showColumns = this.simplifyTableColumnsProperty(this.columns)
    // 保存到缓存
    this.saveDataToStorage(this.taskTypeColumnsStorageKey, showColumns)
    this.$message.success(this.$t('common.base.saveSuccess'));
    // 重新渲染表格
    this.reRenderTable()
  }
}

export default BizListViewTaskMethods
